#pragma once
#include<iostream>
#include<pthread.h>
#include<queue>
using namespace std;

//描述所有线程的共享资源
template <typename T>
class BlockQueue{
public:
    BlockQueue()=default;
    BlockQueue(int cap):cap_(cap)
    {
        pthread_mutex_init(&mutex_,nullptr);  //初始化锁和条件变量  
        pthread_cond_init(&cond_p,nullptr);
        pthread_cond_init(&cond_c,nullptr);
    }
    ~BlockQueue(){
        pthread_mutex_destroy(&mutex_); //摧毁锁和条件变量   
        pthread_cond_destroy(&cond_p);
        pthread_cond_destroy(&cond_c);
    }

    void push(const T& data){  //生产
        pthread_mutex_lock(&mutex_);//申请锁,不成功则阻塞等待
        while(q_.size() >= cap_){ 
            pthread_cond_wait(&cond_p,&mutex_);//不满足生产条件,挂起等待,直到可以生产而被唤醒,挂起自动释放锁
        }

        q_.push(data);//想生产就生产吗??不行,得不超过cap_容量,使用条件变量约束

        pthread_cond_signal(&cond_c);//刚刚已经生产了一个资源,唤醒一个挂起的消费者
        pthread_mutex_unlock(&mutex_);
    }

    T pop(){  //消费
        pthread_mutex_lock(&mutex_);//申请锁,不成功则阻塞等待
        while(q_.size() == 0){
            pthread_cond_wait(&cond_c,&mutex_);//不满足消费条件,挂起等待,直到可以消费而被唤醒,挂起自动释放锁
        }

        T data = q_.front();
        q_.pop();

        pthread_cond_signal(&cond_p);
        pthread_mutex_unlock(&mutex_);
        return data;
    }
public:
    queue<T> q_;//队列
    int cap_;//容量
    pthread_mutex_t mutex_;//互斥锁
    pthread_cond_t cond_p;//生产者条件变量
    pthread_cond_t cond_c;//消费者条件变量
};